Link to this headingNoise Protocol

#Derive ECDH

Link to this headingWireguard

Example Python Wireguard Connection:

import base64 import datetime from hashlib import blake2s import socket import struct from scapy.layers.inet import IP, ICMP from noise.connection import NoiseConnection, Keypair address = ('192.168.88.12', 51820) our_private = base64.b64decode('KAeB4HGe78vSqQ0PUMNh6UOvEcvtvK5wcVJFhato3Vg=') their_public = base64.b64decode('p0BYGoPj5OW4CfOmC8Etu2BHjXH7iLIXulVvZeTfHRQ=') #preshared = bytes.fromhex('5573657231003132333435363344000000000000000000000000000000000000') preshared = bytes.fromhex('0000000000000000000000000000000000000000000000000000000000000000') prologue = b'WireGuard v1 zx2c4 [email protected]' noise = NoiseConnection.from_name(b'Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s') noise.set_as_initiator() noise.set_keypair_from_private_bytes(Keypair.STATIC, our_private) noise.set_keypair_from_public_bytes(Keypair.REMOTE_STATIC, their_public) noise.set_psks(psk=preshared) noise.set_prologue(prologue) noise.start_handshake() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) print("Part 1") # 1. Prepare and send handshake initiation packet now = datetime.datetime.now() tai = struct.pack('!qi', 4611686018427387914 + int(now.timestamp()), int(now.microsecond * 1e3)) initiation_packet = b'\x01' # Type: initiation initiation_packet += b'\x00' * 3 # Reserved initiation_packet += struct.pack('<i', 28) # Sender index: 28 (arbitrary) initiation_packet += noise.write_message(payload=tai) mac_key = blake2s(b'mac1----' + their_public).digest() initiation_packet += blake2s(initiation_packet, digest_size=16, key=mac_key).digest() initiation_packet += b'\x00' * 16 sock.sendto(initiation_packet, address) print("Part 2") # 2. Receive response to finalize handshake response_packet = sock.recv(92) print(response_packet) assert response_packet[0] == 2 # Type: response assert response_packet[1:4] == b'\x00' * 3 # Reserved their_index, our_index = struct.unpack('<ii', response_packet[4:12]) assert our_index == 28 payload = noise.read_message(response_packet[12:60]) assert payload == b'' assert noise.handshake_finished print("Part 3") # 3. Prepare, encrypt and send ping packet icmp_packet = ICMP(type=8, id=921, seq=438)/b'WireGuard' ip_packet = IP(proto=1, ttl=20, src="10.200.100.2", dst="10.200.100.1", id=0)/icmp_packet ping_packet = b'\x04' # Type: data ping_packet += b'\x00' * 3 # Reserved ping_packet += struct.pack('<iq', their_index, 0) ping_packet += noise.encrypt(bytes(ip_packet)) sock.sendto(ping_packet, address) print("Part 4") # 4. Retrieve ping response, decrypt and verify encrypted_response = sock.recv(2048) #print(encrypted_response) assert encrypted_response[0] == 4 # Type: data assert encrypted_response[1:4] == b'\x00' * 3 # Reserved our_index, nonce = struct.unpack('<iq', encrypted_response[4:16]) assert our_index == 28 assert nonce == 0 ip = noise.decrypt(encrypted_response[16:]) ip = IP(ip) ip.display() """ assert icmp.type == 0 assert icmp.code == 0 assert icmp.id == 921 assert icmp.seq == 438 assert payload.load == b'WireGuard' """ print("Part 5") # 5. Send keepalive keepalive = b'\x04' # Type: data keepalive += b'\x00' * 3 # Reserved keepalive += struct.pack('<iq', their_index, 1) keepalive += noise.encrypt(b'') sock.sendto(keepalive, address) print("Part 6")